import { BaseCommand, TSelectRanage, TMergeCell } from '../types/common.interface';
import { TableDatas } from '../cors/table-datas';
import { RenderTrigger } from '../cors/render-trigger';
import { Row } from '../cors/row';
import { NBorder } from '../types/style.interface';
import { clone } from '../utils/deep-clone';
import { addAttribute } from '../utils/object-helper';
export type TBorderPosition = 'inside'|'left'|'none'|'top'|'outer'|'right'|'bottom'|'all';
export class BorderCommand extends BaseCommand {
    protected pastBorder: {row: number, col: number, border: NBorder.IBorder}[] = [];
    constructor(
        protected datas: TableDatas, 
        protected range: TSelectRanage, 
        protected renderTrigger: RenderTrigger,
        protected border: NBorder.IBorderStyle | null,
        protected borderPosition: 'inside'|'left'|'none'|'top'|'outer'|'right'|'bottom'|'all'
    ){
        super();
    }
    public execute() {
        for(let i = this.range.row; i < this.range.row + this.range.rowspan; i++) {
            let rowInstance = this.datas.getRow(i);
            for(let j = this.range.col; j < this.range.col + this.range.colspan; j++) {
                let merge = this.datas.mergeCell.getMerge(i,j);
                if(merge != null && merge.row != i && merge.col != j) {
                    continue;
                }
                let cellInstance = rowInstance.getCell(j);
                this.pastBorder.push({
                    row: i,
                    col: j,
                    border: clone(cellInstance.border)
                });
                switch(this.borderPosition) {
                    case 'all':
                        if(this.border == null) {
                            cellInstance.border == null;
                        } else {
                            cellInstance.border = {
                                top: this.border,
                                left: this.border,
                                bottom: this.border,
                                right: this.border
                            };
                        } 
                    break;
                    case 'none':
                        cellInstance.border = null;
                    break;
                    case 'left':
                        if(j == this.range.col || (merge != null && merge.col + merge.colspan - 1 == this.range.col)) {
                            cellInstance.border = addAttribute(cellInstance.border, {left: this.border});
                        }
                    break;
                    case 'right':
                        if(j == this.range.colspan + this.range.col - 1 
                            || (merge != null && this.range.colspan + this.range.col - 1 == merge.col + merge.colspan - 1)) {
                            cellInstance.border = addAttribute(cellInstance.border, {right: this.border});
                        }
                    break;
                    case 'top':
                        if(i == this.range.row) {
                            cellInstance.border = addAttribute(cellInstance.border, {top: this.border});
                        }
                    break;
                    case 'bottom':
                        if(i == this.range.row + this.range.rowspan - 1 
                            || (merge != null && this.range.row + this.range.rowspan - 1 == merge.row + merge.rowspan - 1)) {
                            cellInstance.border = addAttribute(cellInstance.border, {bottom: this.border});
                        }
                    break;
                    case 'inside':
                        if(this.range.rowspan > 1) {
                            if(i == this.range.row) {
                                if(merge != null) {
                                    if(merge.row + merge.rowspan != this.range.row + this.range.rowspan) {
                                        cellInstance.border = addAttribute(cellInstance.border, {bottom: this.border});
                                    }
                                } else {
                                    cellInstance.border = addAttribute(cellInstance.border, {bottom: this.border});
                                }
                            }
                            if(i == this.range.row + this.range.rowspan - 1) {
                                cellInstance.border = addAttribute(cellInstance.border, {top: this.border});
                            }
                            if(i > this.range.row && i < this.range.row + this.range.rowspan - 1) {
                                if(merge != null) {
                                    if(merge.row + merge.rowspan != this.range.row + this.range.rowspan) {
                                        cellInstance.border = addAttribute(cellInstance.border, {top: this.border, bottom: this.border});
                                    }
                                } else {
                                    cellInstance.border = addAttribute(cellInstance.border, {top: this.border, bottom: this.border});
                                } 
                            }
                        }
                        if(this.range.colspan > 1) {
                            if(j == this.range.col) {
                                if(merge != null) {
                                    if(merge.col + merge.colspan != this.range.col + this.range.colspan) {
                                        cellInstance.border = addAttribute(cellInstance.border, {right: this.border});
                                    }
                                } else {
                                    cellInstance.border = addAttribute(cellInstance.border, {right: this.border});
                                }
                            }
                            if(j == this.range.col + this.range.colspan - 1) {
                                cellInstance.border = addAttribute(cellInstance.border, {left: this.border});
                            }
                            if(j > this.range.col && j < this.range.col + this.range.colspan - 1) {
                                if(merge != null) {
                                    if(merge.col + merge.colspan != this.range.col + this.range.colspan) {
                                        cellInstance.border = addAttribute(cellInstance.border, {left: this.border, right: this.border});
                                    }
                                } else {
                                    cellInstance.border = addAttribute(cellInstance.border, {left: this.border, right: this.border});
                                }
                            }
                        }
                    break;
                    case 'outer':
                        if(i == this.range.row) {
                            cellInstance.border = addAttribute(cellInstance.border, {top: this.border});
                        }
                        if(i == this.range.row + this.range.rowspan - 1 
                            || (merge != null && this.range.row + this.range.rowspan == merge.row + merge.rowspan)
                            ) {
                            cellInstance.border = addAttribute(cellInstance.border, {bottom: this.border});
                        }
                        if(j == this.range.col) {
                            cellInstance.border = addAttribute(cellInstance.border, {left: this.border});
                        }
                        if(j == this.range.col + this.range.colspan - 1 
                            || (merge != null && merge.col + merge.colspan == this.range.col + this.range.colspan)
                            ) {
                            cellInstance.border = addAttribute(cellInstance.border, {right: this.border});
                        }
                    break;
                    default:
                        console.warn(`unexpect border setting!param: ${this.borderPosition}`);
                }
                rowInstance.setCell(j, cellInstance);
                this.datas.setRow(rowInstance, i);
                this.renderTrigger.triggerRenderAll();
            }
        }
        return true;
    }
    public redo() {
        for(let item of this.pastBorder) {
            let rowInstance = this.datas.getRow(item.row);
            let cellInstance = rowInstance.getCell(item.col);
            cellInstance.border = item.border;
            rowInstance.setCell(item.col, cellInstance);
            this.datas.setRow(rowInstance, item.row);
        }
        this.renderTrigger.triggerRenderAll();
        return true;
    }
}